import {
  Injectable,
  InternalServerErrorException,
  ConflictException,
  NotFoundException,
  ForbiddenException,
  BadRequestException,
} from '@nestjs/common';
import { CreateTagDto } from './dto/create-tag.dto';
import { UpdateTagDto } from './dto/update-tag.dto';
import { PrismaService } from 'src/services/prisma.service';
import { tags } from '@prisma/client';
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
import type { Tag, QueryTagInfo } from 'src/typing';

@Injectable()
export class TagsService {
  constructor(private prisma: PrismaService) {}
  async createTag(user_id: number, tagInfo: CreateTagDto): Promise<tags> {
    try {
      return await this.prisma.tags.create({
        data: {
          tag_name: tagInfo.tag_name,
          user: { connect: { user_id } },
        },
      });
    } catch (error) {
      if (
        error instanceof PrismaClientKnownRequestError &&
        error.code === 'P2002'
      ) {
        throw new ConflictException('该标签已经存在');
      }
      throw new InternalServerErrorException('创建标签失败');
    }
  }

  async filterAllTags({
    user_id,
    page,
    pageSize,
    keywords = '',
  }: QueryTagInfo): Promise<[Tag[], number]> {
    const [tags, total] = await Promise.all([
      this.prisma.tags.findMany({
        ...(page &&
          pageSize && { skip: (page - 1) * pageSize, take: +pageSize }),
        where: {
          user_id,
          ...(keywords && { tag_name: { contains: keywords } }),
        },
        select: {
          tag_id: true,
          tag_name: true,
        },
        orderBy: [{ tag_id: 'desc' }],
      }),
      this.prisma.tags.count({
        where: {
          user_id,
          ...(keywords && { tag_name: { contains: keywords } }),
        },
      }),
    ]);
    return [tags, total];
  }

  async getTag(tag_id: number): Promise<tags | null> {
    const tag = await this.prisma.tags.findUnique({
      where: { tag_id },
    });
    return tag;
  }

  async updateTag(tag_id: number, updateTagInfo: UpdateTagDto) {
    try {
      return this.prisma.tags.update({
        where: { tag_id },
        data: updateTagInfo,
      });
    } catch (error) {
      throw new InternalServerErrorException('编辑失败');
    }
  }

  async deleteTag(tag_id: number) {
    try {
      await this.prisma.tags.delete({
        where: { tag_id },
      });
    } catch (error) {
      throw new InternalServerErrorException('删除失败');
    }
  }

  async identifyAuth(user_id: number, tag_id: number): Promise<void> {
    const tag = await this.getTag(tag_id);
    if (tag && user_id !== tag.user_id) {
      throw new ForbiddenException('无该标签相关权限');
    }
  }

  /**
   * 处理标签
   *  标签最多3个，过滤无效标签，返回存在的标签
   *
   * @param {number[]} tags - 标签ID数组，最多包含3个标签
   * @returns  {number[]} - 返回有效标签ID数组
   */
  async handleTags(tags: number[]): Promise<Tag[]> {
    if (tags.length > 3) {
      throw new BadRequestException('标签最多3个');
    }
    // 过滤无效标签
    const tagDetails = await Promise.all(
      tags.map(async (tag_id) => {
        const tagInfo = await this.getTag(+tag_id);
        if (tagInfo) {
          return {
            tag_id: tagInfo.tag_id,
            tag_name: tagInfo.tag_name,
          };
        }
        return null;
      }),
    );
    return tagDetails.filter((tag) => tag !== null);
  }
}
